﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading;
using System.Data;
using SMSPanasonic.Business;
using System.Text.RegularExpressions;
using SMSPanasonic.Data;

namespace SMSPanasonic
{
    class SMSMOSend
    {
        private EventLog _serviceEventLog;
        private bool _thread_working_flag = false;
        private bool _serviceStarted;
        private int _interval = Properties.Settings.Default.IntevalDefaultGetReport;
        private static object _log = new object();
        public bool ServiceStarted
        {
            get
            {
                return _serviceStarted;
            }
            set
            {
                _serviceStarted = value;
            }
        }
        
        public int Interval
        {
            get
            {
                return _interval;
            }
        }

        public SMSMOSend(EventLog log)
        {
            _serviceEventLog = log;
        }

        public void ExecuteTask()
        {
            DateTime lastRunTime = DateTime.Now;
            while (_serviceStarted)
            {
                if (((TimeSpan)(DateTime.Now.Subtract(lastRunTime))).TotalMilliseconds >= _interval && !_thread_working_flag)
                {
                    _thread_working_flag = true;
                    try
                    {
                        if (Common.isDatabaseAlive(AppConfig.ConnectionString) == ConnectionState.Open)
                        {
                            lock (_log)//Mỗi lượt xử lý dữ liệu thì phải lock lại không cho phép nhiều thread
                            {
                                ProcessingData(SmsMoWaiting.GetByTop(AppConfig.BatchSize));
                            }
                        }
                    }
                    catch (Exception ext)
                    {
                        try
                        {
                            Common.WriteLog(ext, "GetMOWaiting");
                        }
                        catch (Exception extend)
                        {
                            _serviceEventLog.WriteEntry(extend.Message);
                        }
                    }
                    finally
                    {
                        _thread_working_flag = false;
                    }
                }
                // yield
                if (_serviceStarted)
                {
                    Thread.Sleep(new TimeSpan(0, 0, 0, 0, 100));
                }
            }
            Thread.CurrentThread.Abort();
        }

        #region Private method
        private void ProcessingData(DataTable dtSource)
        {
            if (dtSource == null || dtSource.Rows.Count == 0) return;
            DataTable dtMoStatistic = MakeBulkTable.MakeSmsMoStatisticTable();
            DataTable dtMtReport = MakeBulkTable.MakeSmsMtReportTable();
            DataTable dtMtWaiting = MakeBulkTable.MakeSmsMtWaitingTable();
            DataTable dtMoWatting = MakeBulkTable.MakeSmsMoWaitingTable();
            DataTable dtWarrantyWaiting = MakeBulkTable.MakeWarrantyWaitingTable();
            DataTable dtCustomerPhone = MakeBulkTable.MakeCustomerPhoneTable();
            DataTable dtpaSmsStatistic = MakeBulkTable.MakePaSmsStatisticTable();
            try
            {
                #region Duyệt bảng dữ liệu và xử lý từng dòng nghiệp vụ
                foreach (DataRow row in dtSource.Rows)
                {
                    try
                    {
                        if (row["RetryOnFailReqTimes"].Equals(DBNull.Value))
                            row["RetryOnFailReqTimes"] = 10;
                        DataRow mtRow = dtMtWaiting.NewRow();
                        string message = ((string)row["Message"]).ToNormalString();
                        string action = GetAction(message);
                        switch (action)
                        {
                            case "DK":
                                mtRow.ItemArray = SmsMoWaiting.RegisterWarrany(row, ref dtWarrantyWaiting, ref dtCustomerPhone, ref dtpaSmsStatistic).ItemArray;
                                break;
                            case "GH":
                                mtRow.ItemArray = SmsMoWaiting.ExtentWarranty(row, ref dtWarrantyWaiting, ref dtCustomerPhone, ref dtpaSmsStatistic).ItemArray;
                                break;
                            case "SL":
                                mtRow.ItemArray = SmsMoWaiting.PanaSL(row).ItemArray;
                                break;
                            case "KT":
                                mtRow.ItemArray = SmsMoWaiting.PanaKT(row).ItemArray;
                                break;
                            case "TH":
                                mtRow.ItemArray = SmsMoWaiting.PanaTH(row).ItemArray;
                                break;
                            case "ERROR":
                                string msg = MessagePattern.GetMessage(eMessagePattern.PHANHOISAICUPHAP);
                                mtRow["MtGuid"] = Guid.NewGuid();
                                mtRow["MoGuid"] = row["MoGuid"];
                                mtRow["ShortCode"] = row["ShortCode"];
                                mtRow["DestAddr"] = row["Subs"];
                                mtRow["OperatorID"] = row["OperatorID"];
                                mtRow["Message"] = msg;
                                mtRow["CooperateID"] = row["CooperateID"];
                                mtRow["Status"] = "PENDING";
                                mtRow["SentTime"] = DateTime.Now;
                                mtRow["CDRIndicator"] = "FREE";
                                mtRow["MTType"] = SmsShortCode.GetMtType(row["ShortCode"].ToString());//SmsShortCode.GetOne(row["ShortCode"].ToString()).MTType;
                                mtRow["RetryOnFailReqTimes"] = Properties.Settings.Default.RetryOnFailReqTimes;
                                mtRow["RetryOnTimeOutReqTimes"] = Properties.Settings.Default.RetryOnTimeOutReqTimes;
                                mtRow["RetryOnFailReqDuration"] = Properties.Settings.Default.RetryOnFailReqDuration;
                                mtRow["RetryOnTimeOutReqDuration"] = Properties.Settings.Default.RetryOnTimeOutReqDuration;
                                break;
                        }
                        dtMtWaiting.Rows.Add(mtRow);
                        dtMtReport.Rows.Add(mtRow["MtGuid"], mtRow["SentTime"], mtRow["Status"]);                        
                        DataRow moRow = dtMoStatistic.NewRow();
                        moRow.ItemArray = row.ItemArray;
                        dtMoStatistic.Rows.Add(moRow);
                    }
                    catch (Exception ex)
                    {
                        if (row["RetryOnFailReqTimes"] is int && (int)row["RetryOnFailReqTimes"] > 0)
                        {
                            DataRow moRow = dtMoWatting.NewRow();
                            moRow.ItemArray = row.ItemArray;
                            moRow["MoGuid"] = Guid.NewGuid();
                            moRow["Status"] = "RETRY";
                            moRow["RetryOnFailReqTimes"] = (int)moRow["RetryOnFailReqTimes"] - 1;
                            dtMoWatting.Rows.Add(moRow);

                            try
                            {
                                Common.WriteLog(ex, "SMSMOSend");
                                Logs log = new Logs();
                                log.LogType = "SMSMOSend";
                                log.LogMessage = string.Format("PANASONIC [ERROR]=>  GUID ={0}; DESTADDR = {1}; Message = {2} RETRY!", row["MoGuid"], row["Subs"], row["Message"]);
                                log.LogTime = DateTime.Now;
                                log.LogTrace = "SMSMOSend Item";
                                log.LogSource = "Lỗi xử lý do hệ thống SMSPanaSonic";
                                log.Status = true;
                                log.Save();
                            }
                            catch (Exception extend)
                            {
                                _serviceEventLog.WriteEntry(extend.Message);
                            }
                        }
                        else
                        {
                            try
                            {
                                Logs log = new Logs();
                                log.LogType = "SMSMOSend";
                                log.LogMessage = string.Format("PANASONIC [ERROR]=>  GUID ={0}; DESTADDR = {1}; Message = {2} DA HET SO LAN Retry!", row["MoGuid"], row["Subs"], row["Message"]);
                                log.LogTime = DateTime.Now;
                                log.LogTrace = "SMSMOSend Item";
                                log.LogSource = "Lỗi xử lý do hệ thống SMSPanaSonic";
                                log.Status = true;
                                log.Save();
                            }
                            catch (Exception extend)
                            {
                                _serviceEventLog.WriteEntry(extend.Message);
                            }
                        }
                    }
                }
                #endregion Duyệt bảng dữ liệu và xử lý từng dòng nghiệp vụ

                #region Insert dữ liệu vào các bảng dữ liệu
                //Insert dữ liệu vào pa_WarrantyWaiting
                if (dtWarrantyWaiting.Rows.Count > 0)
                {
                    pa_WarrantyWaiting.Insert(dtWarrantyWaiting);
                }
                //Insert hoặc cập nhật dữ liệu vào pa_Customer
                if (dtCustomerPhone.Rows.Count > 0)
                {
                    pa_Customer.InsertOrUpdate(dtCustomerPhone);
                }
                //Insert hoặc cập nhật dữ liệu vào pa_SmsStatistic
                if (dtpaSmsStatistic.Rows.Count > 0)
                {
                    pa_SmsStatistic.InsertOrUpdate(dtpaSmsStatistic);
                }
                //Insert dữ liệu xử lý lỗi ngược lại SmsMoWaiting
                if (dtMoWatting.Rows.Count > 0)
                {
                    SmsMoWaiting.Insert(dtMoWatting);
                }
                //Insert dữ liệu vào SmsMoStatistic
                if (dtMoStatistic.Rows.Count > 0)
                {
                    SmsMoStatistic.Insert(dtMoStatistic);
                }
                //Insert dữ liệu vào SmsMtReport
                if (dtMtReport.Rows.Count > 0)
                {
                    SmsMtReport.Insert(dtMtReport);
                }
                //Insert dữ liệu vào SmsMtStatistic và SmsMtWaiting
                if (dtMtWaiting.Rows.Count > 0)
                {
                    SmsMtStatistic.Insert(dtMtWaiting);
                    SmsMtWaiting.Insert(dtMtWaiting);
                }
                #endregion Insert dữ liệu vào các bảng dữ liệu
            }
            catch (Exception ex)
            {
                try
                {
                    Common.WriteLog(ex, "SMSMOSend");
                }
                catch (Exception extend)
                {
                    _serviceEventLog.WriteEntry(extend.Message);
                }
            }
            finally
            {
                dtMoStatistic.Dispose();
                dtMtReport.Dispose();
                dtMtWaiting.Dispose();
                dtMoWatting.Dispose();
                dtWarrantyWaiting.Dispose();
                dtCustomerPhone.Dispose();
                dtpaSmsStatistic.Dispose();
                dtSource.Dispose();
            }
        }

        public string GetAction(string input)
        {
            string patternDK = @"^pana\s\d+\s(\w|\d|-|\(|\)|\.)+\s(\w|\d|-|\(|\)|\.)+$";
            string patternGH = @"^pana\s\d+\s(\w|\d|-|\(|\)|\.)+\s(\w|\d|-|\(|\)|\.)+\s(\w|\d)+$";
            string patternSL = @"^pana\ssl";
            string patternKT = @"^pana\skt";
            string patternTH = @"^pana\sth";
            if (Regex.IsMatch(input, patternDK, RegexOptions.IgnoreCase))
                return "DK";
            if (Regex.IsMatch(input, patternGH, RegexOptions.IgnoreCase))
                return "GH";
            if (Regex.IsMatch(input, patternSL, RegexOptions.IgnoreCase))
                return "SL";
            if (Regex.IsMatch(input, patternKT, RegexOptions.IgnoreCase))
                return "KT";
            if (Regex.IsMatch(input, patternTH, RegexOptions.IgnoreCase))
                return "TH";
            return "ERROR";
        }

        #endregion
    }
}
